<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <title>tiptap menus 菜单 - itxst.com</title>
    <meta name="keywords" content="tiptap menus 菜单" />
    <meta name="description" content="tiptap 编辑器非常简洁，你可以完全的定制它的外观，菜单也一样。tiptap提供的 API 来触发命令和添加活动状态，tiptap提供了一些实用程序和组件使菜单的定位更容易。" />
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
    <meta http-equiv="Content-Language" content="zh-CN">
    <link rel="shortcut icon" href="/img/favicon.ico" type="image/x-icon" />
    <link href="/css/zt.css?ver=1.6.6" rel="stylesheet" type="text/css" media="all" />
    <script type="text/javascript" language="javascript" src="/js/jquery.js?ver=1.6.6"></script>
    <script type="text/javascript" src="/js/highlight/highlight.min.js?ver=1.6.6"></script>
    <link rel="stylesheet" type="text/css" href="/js/highlight/styles/vs2015x.css?ver=1.6.6">
    <script type="text/javascript" language="javascript" src="/js/comm.js?ver=1.6.6"></script>
    <script type="text/javascript" language="javascript" src="/js/zt.js?ver=1.6.6"></script>
    <script type="text/javascript" charset="utf-8" src="/js/layer/layer.js?ver=1.6.6"></script>
    <link rel="alternate" media="only screen and(max-width: 640px)" href="http://m.itxst.com/tiptap/menus.html" >
    <!--[if lte IE 9]>
    <script src="/js/respond/respond.js?ver=1.6.6"></script>
    <![endif]-->
</head>
<body>
    <div class="body"  >
        <div class="header">
            <div class="naver">
                <div class="logo">
                    <a href="/"><img src="/img/logov31.png" /></a>
                </div>
                <div class="naver-left">
                 <a href="/tiptap/tutorial.html">tiptap 中文文档</a>
                </div>
                <div class="naver-search">
                    <div class="naver-search-txt">
                        <input type="text" id="keyword" placeholder="Please enter the keyword" data-topic="tiptap">
                    </div>
                    <div class="naver-search-btn"><a href="javascript:void(0)" onclick="Search()">Search</a></div>
                </div>
                 <div class="naver-right"> 
                        <a href="/ag-grid/tutorial.html">AG-GRID</a> 
                        <a href="/tiptap/tutorial.html">Tiptap</a> 
                        <a href="/css-flex/tutorial.html">CSS-FLEX</a> 
                        <a href="/Bootstrap-Table/QuickStart.html">Bootstrap-Table</a> 
                </div>
            </div>
            <div class="path">
                
            </div>
        </div>
        <div class="clearfix"></div>
        <div class="pagew">
        <div class="page" >
            <div class="page-body">
                <div class="content-detail">
                    <h1>tiptap menus 菜单</h1>
               
               <p class="p"><strong>tiptap</strong>编辑器非常简洁，你可以完全的定制它的外观， <strong>menus</strong>菜单也一样。 <strong>tiptap</strong>提供的<strong>API</strong>来触发命令和添加活动状态， <strong>tiptap</strong>提供了一些实用程序和组件使菜单的定位更容易。</p><h2>固定菜单</h2><p class="p"><strong>tiptap</strong>并没有提供类似其他编辑器的顶部菜单组件，但是你可以自己用任何html元素来实现。</p><h2>气泡菜单</h2><p>当用户选中编辑器中的文字时，tiptap将会在光标上方弹出菜单,JavaScript中用法如下</p><pre class="brush:js;toolbar:false"><code class="language-javascript">import { Editor } from '@tiptap/core'
import BubbleMenu from '@tiptap/extension-bubble-menu'

new Editor({
  extensions: [
    BubbleMenu.configure({
      element: document.querySelector('.menu'),
    }),
  ],
})</code></pre><p>tiptap vue3 中气泡菜单用法如下</p><pre class="brush:html;toolbar:false;"><code class="language-html">&lt;template&gt;
  &lt;div&gt;
    &lt;bubble-menu :editor="state.editor" :tippy-options="{ duration: 100 }" v-if="state.editor"&gt;
      &lt;button @click="state.editor.chain().focus().toggleBold().run()"
        :class="{ 'is-active': state.editor.isActive('bold') }"&gt;
        bold
      &lt;/button&gt;
      &lt;button @click="state.editor.chain().focus().toggleItalic().run()"
        :class="{ 'is-active': state.editor.isActive('italic') }"&gt;
        italic
      &lt;/button&gt;
      &lt;button @click="state.editor.chain().focus().toggleStrike().run()"
        :class="{ 'is-active': state.editor.isActive('strike') }"&gt;
        strike
      &lt;/button&gt;
    &lt;/bubble-menu&gt;
    &lt;editor-content :editor="state.editor" /&gt;
  &lt;/div&gt;
&lt;/template&gt;
&lt;script setup&gt;
/*
 tiptap 中文文档
 https://www.itxst.com/tiptap/tutorial.html
*/
import { onMounted, reactive } from "vue";
import { BubbleMenu, Editor, EditorContent } from "@tiptap/vue-3";
import StarterKit from "@tiptap/starter-kit";

const state = reactive({
  editor: new Editor({
    content: "&lt;p&gt;Tiptap 中文文档&lt;/p&gt;",
    extensions: [StarterKit],
    autofocus: true,
    editable: true,
  }) as any,
});

onMounted(() =&gt; { });
&lt;/script&gt;
&lt;style scoped&gt;
.editor {
  margin: 10px 20px;
  width: 390px;
  border-radius: 6px;
}

.editor:deep(.ProseMirror) {
  color: red;
  border: solid 1px #ddd;
  padding: 0px 6px;
  border-radius: 6px;
}
&lt;/style&gt;</code></pre><p><a class="btntry" href="//debug.itxst.com/js/mvnynjq2" target="_blank" title="在线试一试">在 Vue2 中试一试</a></p><p>react 中气泡菜单用法如下</p><pre class="brush:js;toolbar:false"><code class="language-javascript">import './styles.scss'
import { BubbleMenu, EditorContent, useEditor } from '@tiptap/react'
import StarterKit from '@tiptap/starter-kit'
import React, { useEffect } from 'react'

export default () =&gt; {
  const editor = useEditor({
    extensions: [
      StarterKit,
    ],
    content: `
      &lt;p&gt;
        Hey, try to select some text here. There will popup a menu for selecting some inline styles. Remember: you have full control about content and styling of this menu.
      &lt;/p&gt;
    `,
  })

  const [isEditable, setIsEditable] = React.useState(true)

  useEffect(() =&gt; {
    if (editor) {
      editor.setEditable(isEditable)
    }
  }, [isEditable, editor])

  return (
    &lt;&gt;
      &lt;div&gt;
        &lt;input type="checkbox" checked={isEditable} onChange={() =&gt; setIsEditable(!isEditable)} /&gt;
        Editable
      &lt;/div&gt;
      {editor &amp;&amp; &lt;BubbleMenu editor={editor} tippyOptions={{ duration: 100 }}&gt;
        &lt;button
          onClick={() =&gt; editor.chain().focus().toggleBold().run()}
          className={editor.isActive('bold') ? 'is-active' : ''}
        &gt;
          bold
        &lt;/button&gt;
        &lt;button
          onClick={() =&gt; editor.chain().focus().toggleItalic().run()}
          className={editor.isActive('italic') ? 'is-active' : ''}
        &gt;
          italic
        &lt;/button&gt;
        &lt;button
          onClick={() =&gt; editor.chain().focus().toggleStrike().run()}
          className={editor.isActive('strike') ? 'is-active' : ''}
        &gt;
          strike
        &lt;/button&gt;
      &lt;/BubbleMenu&gt;}
      &lt;EditorContent editor={editor} /&gt;
    &lt;/&gt;
  )
}</code></pre><h2>浮动菜单</h2><p class="p">当点击tiptap编辑器空白行时，将会显示浮动的菜单，下面的代码将会展示在JS、VUE、React中的使用方法。</p><p>在js中的使用方法</p><pre class="brush:js;toolbar:false"><code class="language-javascript">import { Editor } from '@tiptap/core'
import FloatingMenu from '@tiptap/extension-floating-menu'

new Editor({
  extensions: [
    FloatingMenu.configure({
      element: document.querySelector('.menu'),
    }),
  ],
})</code></pre><p>在Vue3中的使用方法</p><pre class="brush:html;toolbar:false;"><code class="language-html">&lt;template&gt;
  &lt;div class="editor"&gt;
    &lt;floating-menu :editor="state.editor" :tippy-options="{ duration: 100 }" v-if="state.editor"&gt;
      &lt;button @click="state.editor.chain().focus().toggleHeading({ level: 1 }).run()" :class="{ 'is-active': state.editor.isActive('heading', { level: 1 }) }"&gt;
        H1
      &lt;/button&gt;
      &lt;button @click="state.editor.chain().focus().toggleHeading({ level: 2 }).run()" :class="{ 'is-active': state.editor.isActive('heading', { level: 2 }) }"&gt;
        H2
      &lt;/button&gt;
      &lt;button @click="state.editor.chain().focus().toggleBulletList().run()" :class="{ 'is-active': state.editor.isActive('bulletList') }"&gt;
        Bullet List
      &lt;/button&gt;
    &lt;/floating-menu&gt;
    &lt;editor-content :editor="state.editor" /&gt;
  &lt;/div&gt;
&lt;/template&gt;
&lt;script setup lang="ts"&gt;
/*
 tiptap 中文文档
 https://www.itxst.com/tiptap/tutorial.html
*/
import { onMounted, reactive } from "vue";
import { FloatingMenu , Editor, EditorContent } from "@tiptap/vue-3";
import StarterKit from "@tiptap/starter-kit";

const state = reactive({
  editor: new Editor({
    content: "&lt;p&gt;Tiptap 中文文档,点击编辑器的空白处试试看&lt;/p&gt;",
    extensions: [StarterKit],
    autofocus: true,
    editable: true,
  }) as any,
});

onMounted(() =&gt; { });
&lt;/script&gt;
&lt;style scoped&gt;
.editor {
  margin: 10px 20px;
  width: 390px;
  border-radius: 6px;
}

.editor:deep(.ProseMirror) {
  color: red;
  border: solid 1px #ddd;
  padding: 0px 6px;
  border-radius: 6px;
  min-height: 160px;
}
&lt;/style&gt;</code></pre><p><a class="btntry" href="//debug.itxst.com/js/vuunaimq" target="_blank" title="在线试一试">在 Vue2 中试一试</a></p><p>在React中的使用方法</p><pre class="brush:js;toolbar:false"><code class="language-javascript">import './styles.scss'
import { EditorContent, FloatingMenu, useEditor } from '@tiptap/react'
import StarterKit from '@tiptap/starter-kit'
import React, { useEffect } from 'react'

export default () =&gt; {
  const editor = useEditor({
    extensions: [
      StarterKit,
    ],
    content: `
      &lt;p&gt;
        This is an example of a Medium-like editor. Enter a new line and some buttons will appear.
      &lt;/p&gt;
      &lt;p&gt;&lt;/p&gt;
    `,
  })


  const [isEditable, setIsEditable] = React.useState(true)


  useEffect(() =&gt; {
    if (editor) {
      editor.setEditable(isEditable)
    }
  }, [isEditable, editor])


  return (
    &lt;&gt;
      &lt;div&gt;
        &lt;input type="checkbox" checked={isEditable} onChange={() =&gt; setIsEditable(!isEditable)} /&gt;
        Editable
      &lt;/div&gt;
      {editor &amp;&amp; &lt;FloatingMenu editor={editor} tippyOptions={{ duration: 100 }}&gt;
        &lt;button
          onClick={() =&gt; editor.chain().focus().toggleHeading({ level: 1 }).run()}
          className={editor.isActive('heading', { level: 1 }) ? 'is-active' : ''}
        &gt;
          h1
        &lt;/button&gt;
        &lt;button
          onClick={() =&gt; editor.chain().focus().toggleHeading({ level: 2 }).run()}
          className={editor.isActive('heading', { level: 2 }) ? 'is-active' : ''}
        &gt;
          h2
        &lt;/button&gt;
        &lt;button
          onClick={() =&gt; editor.chain().focus().toggleBulletList().run()}
          className={editor.isActive('bulletList') ? 'is-active' : ''}
        &gt;
          bullet list
        &lt;/button&gt;
      &lt;/FloatingMenu&gt;}
      &lt;EditorContent editor={editor} /&gt;
    &lt;/&gt;
  )
}
//样式文件
import './styles.scss'
.ProseMirror {  &gt; * + * {    margin-top: 0.75em;  }  ul,  ol {    padding: 0 1rem;  }}</code></pre><h2>菜单命令</h2><p>tiptap编辑器的加粗和颜色菜单是如何让选中的对象/文字改变颜色大小的呢？当鼠标点击对象/文字菜单又是如何知道是加粗菜单还是设置颜色菜单的呢？以下代码表示将选中文字加粗</p><pre class="brush:js;toolbar:false"><code class="language-javascript">editor.chain().focus().toggleBold().run()</code></pre><ul class="p list-paddingleft-2"><li><p><strong>editor</strong>编辑器对象</p></li><li><p><strong>chain</strong>告诉编辑器需要执行命令</p></li><li><p><strong>focus</strong>执行完后让编辑器获得焦点</p></li><li><p><strong>toggleBold</strong>加粗选中的文字</p></li><li><p><strong>run</strong>执行命令</p></li></ul><p>激活状态，当选中文字时可以获取编辑器的激活状态是加粗还是颜色等,下面的代码表示当选中的文字被加粗则给按钮加上“is-active”样式</p><pre class="brush:html;toolbar:false;"><code class="language-html">&lt;button :class="{ 'is-active': editor.isActive('bold') }" @click="editor.chain().focus().toggleBold().run()"&gt;  Bold&lt;/button&gt;</code></pre><p>isActive方法适应nodes 和marks还支持特定的属性，如下代码当设置颜色为#000000，选中这个颜色才能激活颜色菜单</p><pre class="brush:js;toolbar:false"><code class="language-javascript">//选择#000000颜色才返回是否激活状态
editor.isActive('textStyle', { color: '#000000' })
//也可以是正则表达式
editor.isActive('textStyle', { color: /.*/ })</code></pre><h2>文字颜色</h2><pre class="brush:html;toolbar:false"><code class="language-html">&lt;template&gt;
  &lt;div class="editor"&gt;
    &lt;span :class="{'is-active-color': state.editor.isActive('textStyle', {color: 'rgb(0, 0, 0)',})}"&gt;
      {{ state.editor.getAttributes("textStyle").color }}
      &lt;input type="color" @input="onColor" :value="state.editor.getAttributes('textStyle').color" /&gt;
    &lt;/span&gt;
    &lt;editor-content :editor="state.editor" /&gt;
  &lt;/div&gt;
&lt;/template&gt;
&lt;script setup lang="ts"&gt;
/*
 tiptap 中文文档
 https://www.itxst.com/tiptap/tutorial.html
*/
import { onMounted, reactive } from "vue";
import { Editor, EditorContent } from "@tiptap/vue-3";
import StarterKit from "@tiptap/starter-kit";
import Color from "@tiptap/extension-color";
import TextStyle from "@tiptap/extension-text-style";

const state = reactive({
  editor: new Editor({
    content:
      'Tiptap 中文文档,&lt;span style="color: #000000"&gt;点击黑色文字&lt;/span&gt;试试看效果',
    extensions: [
      StarterKit,
      TextStyle,
      Color.configure({
        types: ["textStyle"],
      }),
    ],
    autofocus: true,
    editable: true,
  }) as any,
});

onMounted(() =&gt; { });

//设置颜色
const onColor = ($event: any) =&gt; {
  // debugger;
  state.editor.chain().focus().setColor($event.target.value).run();
};
&lt;/script&gt;
&lt;style scoped&gt;
.editor {
  margin: 10px 20px;
  width: 390px;
  border-radius: 6px;
}

.editor:deep(.ProseMirror) {
  color: red;
  border: solid 1px #ddd;
  padding: 0px 6px;
  border-radius: 6px;
  min-height: 160px;
}

.is-active-color {
  background-color: black;
  padding: 6px 6px;
  color: #fff;
}
&lt;/style&gt;</code></pre>
 
               <h2>
    下载教程 Demo
</h2>
<p class="pe">
   本教程<b>Demo</b>的源码点击这里下载，<a href="https://img1.itxst.com/8/c/8c32fcdc12cb8847c62e405be8a73835.zip" target="_blank" textvalue="Tiptap Demo">Tiptap Demo</a>，下载完成后运行<b>npm i</b>初始化依赖包。
</p>
                </div>
                <div class="content-r">   <a href="/tiptap/tutorial.html" target="_self">
                     <img src="https://img1.itxst.com/0/9/09355b3592a0c16799b504a9f2a70303.png" alt="tiptap 中文文档" />
                    </a>                                                <a href="//www.itxst.com/vue-draggable/tutorial.html" target="_blank">
                                <img src="//img1.itxst.com/b/f/bf9af8368dfac84cd703ef54e1e89d14.png" alt="vue.draggable" />
                            </a>
 
                </div>
            </div>
            <div class="home-menu scroll">
                <div class="tree">
      <a data-level="1" class="leve-1   doc-1   " href="/tiptap/tutorial.html" title="tiptap 中文文档">快速入门</a>
      <a data-level="1" class="leve-1    arrow-2" href="/tiptap/configuration.html" title="Guide 向导">Guide 向导</a>
      <a data-level="2" class="leve-2   doc-1   " href="/tiptap/configuration.html" title="Tiptap 编辑器 Configuration 配置">configuration 配置</a>
      <a data-level="2" class="leve-2   doc-1   " href="/tiptap/roseMirrorapi.html" title="ProseMirror  API">prosemirror  api</a>
      <a data-level="2" class="leve-2   doc-1    doc-2 " href="/tiptap/menus.html" title="tiptap menus 菜单">menus 菜单</a>
      <a data-level="2" class="leve-2   doc-1   " href="/tiptap/styling.html" title="Styling Titpap 样式">styling 样式</a>
      <a data-level="2" class="leve-2   doc-1   " href="/tiptap/output.html" title="Titpap Output 输出格式">output 输出格式</a>
      <a data-level="2" class="leve-2   doc-1   " href="/tiptap/collaborative.html" title="tiptap collaborative 实时协作">collaborative 实时协作</a>
      <a data-level="2" class="leve-2   doc-1   " href="/tiptap/customextensions.html" title="tiptap 自定义扩展">extensions 自定义扩展</a>
      <a data-level="1" class="leve-1    arrow-1" href="/tiptap/api.html" title="tiptap api 列表">API 列表</a>
                 </div>
                 <div  class="clearfix"></div>
            </div>
        </div>
        <div class="clearfix"></div>
           <div class="footer">
© 2023 itxst.com All rights reserved.
</div>

<script>
var _hmt = _hmt || [];
(function() {
  var hm = document.createElement("script");
  hm.src = "https://hm.baidu.com/hm.js?7e15ed96eb8133218e99de8bc1f5cb61";
  var s = document.getElementsByTagName("script")[0];
  s.parentNode.insertBefore(hm, s);
})();
</script>
       </div>
    </div> 
</body>
</html>
